/* * Sun Public License Notice * * The contents of this file are subject to the Sun Public License * Version 1.0 (the "License"). You may not use this file except in * compliance with the License. A copy of the License is available at * http://www.sun.com/ * * The Original Code is Forte for Java, Community Edition. The Initial * Developer of the Original Code is Sun Microsystems, Inc. Portions * Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved. */ package org.netbeans.editor.ext; import java.beans.PropertyChangeEvent; import java.io.Writer; import javax.swing.text.BadLocationException; import javax.swing.text.Document; import org.netbeans.editor.BaseDocument; import org.netbeans.editor.Utilities; import org.netbeans.editor.Syntax; import org.netbeans.editor.SyntaxSupport; import org.netbeans.editor.Analyzer; import org.netbeans.editor.SettingsUtil; import org.netbeans.editor.SettingsChangeEvent; import org.netbeans.editor.ext.ExtSettings; /** * Java indentation services are located here * * @author Miloslav Metelka * @version 1.00 */ public class JavaFormatter extends BaseFormatter { public static final char[] semiCompounds = new char[] { ';', '{', '}' }; public static final String SEMICOLON_RESOLVER_NAME = "semicolon-resolver"; // NOI18N public static final String SEMICOLON_RESOLVER_DESC = "After finding semicolon goes back one line and searches " // NOI18N + "for either '{', '}' or ';'. When one of those characters " // NOI18N + "is found, go to the next line (not for '}') and return indentation " // NOI18N + "for it."; // NOI18N public static final String LEFT_COMPOUND_BRACKET_RESOLVER_NAME = "left-compound-bracket-resolver"; // NOI18N public static final String LEFT_COMPOUND_BRACKET_RESOLVER_DESC = "After finding left compound bracket it searches for the begining " // NOI18N + "of the line with this bracket and adds one indent level."; // NOI18N public static final String RIGHT_COMPOUND_BRACKET_RESOLVER_NAME = "right-compound-bracket-resolver"; // NOI18N public static final String RIGHT_COMPOUND_BRACKET_RESOLVER_DESC = "After finding right compound bracket it returns the indentation " // NOI18N + "of the line with this bracket."; // NOI18N public static final String COLON_RESOLVER_NAME = "colon-resolver"; // NOI18N public static final String COLON_RESOLVER_DESC = "After finding colon, it adds one indent level and returns " // NOI18N + "the indentation."; // NOI18N private boolean parenthesisAddSpace; private boolean compoundBracketAddNL; private boolean commentAddStar; private boolean commentAddSpace; private boolean lastTokenWS; public JavaFormatter() { addResolver(new SemicolonResolver()); addResolver(new LeftCompoundBracketResolver()); addResolver(new RightCompoundBracketResolver()); addResolver(new ColonResolver()); // debugMode |= 65535; // !!! } protected void settingsChange(SettingsChangeEvent evt, Class kitClass) { super.settingsChange(evt, kitClass); String settingName = (evt != null) ? evt.getSettingName() : null; if (settingName == null || ExtSettings.FORMAT_PARENTHESIS_ADD_SPACE.equals(settingName)) { parenthesisAddSpace = SettingsUtil.getBoolean(kitClass, ExtSettings.FORMAT_PARENTHESIS_ADD_SPACE, false); } if (settingName == null || ExtSettings.FORMAT_COMPOUND_BRACKET_ADD_NL.equals(settingName)) { compoundBracketAddNL = SettingsUtil.getBoolean(kitClass, ExtSettings.FORMAT_COMPOUND_BRACKET_ADD_NL, false); } if (settingName == null || ExtSettings.FORMAT_COMMENT_ADD_STAR.equals(settingName)) { commentAddStar = SettingsUtil.getBoolean(kitClass, ExtSettings.FORMAT_COMMENT_ADD_STAR, false); } if (settingName == null || ExtSettings.FORMAT_COMMENT_ADD_SPACE.equals(settingName)) { commentAddSpace = SettingsUtil.getBoolean(kitClass, ExtSettings.FORMAT_COMMENT_ADD_SPACE, false); } } public boolean getParenthesisAddSpace() { return parenthesisAddSpace; } public boolean getCompoundBracketAddNL() { return compoundBracketAddNL; } public boolean getCommentAddStar() { return commentAddStar; } public boolean getCommentAddSpace() { return commentAddSpace; } /** Indents the current line. Should not affect any other * lines. * @param doc the document to work on * @param offset the offset of a character on the line * @return new offset of the original character */ public int indentLine (Document d, int offset) { if (d instanceof BaseDocument) { BaseDocument doc = (BaseDocument)d; int indent; try { indent = findAnyIndent((BaseDocument)doc, offset); if (indent < 0) { indent = 0; } indent = roundIndent(indent); int firstNB = Utilities.getRowFirstNonWhite(doc, offset); if (firstNB >= 0) { if (doc.getChars(firstNB, 1)[0] == '}') { indent = Math.max(indent - getShiftWidth(), 0); } } } catch (BadLocationException e) { e.printStackTrace(); indent = 0; } offset += indent; } return offset; } public class SemicolonResolver implements Resolver { public String getName() { return SEMICOLON_RESOLVER_NAME; } public String getDesc() { return SEMICOLON_RESOLVER_DESC; } public char getHotChar() { return ';'; } public int resolve(BaseDocument doc, int pos, int hotCharPos) { try { SyntaxSupport sup = doc.getSyntaxSupport(); int curBolPos = Utilities.getRowStart(doc, hotCharPos, -1); while (curBolPos != -1) { if (!sup.isRowValid(curBolPos)) { int lastCharPos = sup.getRowLastValidChar(curBolPos); if (lastCharPos != -1) { char lastChar = doc.getChars(lastCharPos, 1)[0]; switch (lastChar) { case ';': case '}': case '{': case ':': int nextBol = Utilities.getRowStart(doc, curBolPos, +1); return Utilities.getRowIndent(doc, nextBol, true); } } else { break; } } curBolPos = Utilities.getRowStart(doc, curBolPos, -1); } // no previous line found, use the line with ';' return Utilities.getRowIndent(doc, hotCharPos); } catch (BadLocationException e) { return -1; } } } public class LeftCompoundBracketResolver implements Resolver { public String getName() { return LEFT_COMPOUND_BRACKET_RESOLVER_NAME; } public String getDesc() { return LEFT_COMPOUND_BRACKET_RESOLVER_DESC; } public char getHotChar() { return '{'; } public int resolve(BaseDocument doc, int pos, int hotCharPos) { try { SyntaxSupport sup = doc.getSyntaxSupport(); // !!! matchbracket return Utilities.getRowIndent(doc, hotCharPos) + getShiftWidth(); } catch (BadLocationException e) { return -1; } } } public class RightCompoundBracketResolver implements Resolver { public String getName() { return RIGHT_COMPOUND_BRACKET_RESOLVER_NAME; } public String getDesc() { return RIGHT_COMPOUND_BRACKET_RESOLVER_DESC; } public char getHotChar() { return '}'; } public int resolve(BaseDocument doc, int pos, int hotCharPos) { try { return Utilities.getRowIndent(doc, hotCharPos); } catch (BadLocationException e) { return -1; } } } public class ColonResolver implements Resolver { public String getName() { return COLON_RESOLVER_NAME; } public String getDesc() { return COLON_RESOLVER_DESC; } public char getHotChar() { return ':'; } public int resolve(BaseDocument doc, int pos, int hotCharPos) { try { return Utilities.getRowIndent(doc, hotCharPos) + getShiftWidth(); } catch (BadLocationException e) { return -1; } } } protected Writer createFormatWriter(Document doc, Syntax syntax, Writer underWriter, int startIndent, boolean atLineStart) { return new JavaFormatWriter(this, syntax, underWriter, startIndent, atLineStart); } } /* * Log * 10 Gandalf-post-FCS1.8.1.0 3/8/00 Miloslav Metelka * 9 Gandalf 1.8 2/15/00 Miloslav Metelka parenthesis formatting * 8 Gandalf 1.7 1/13/00 Miloslav Metelka Localization * 7 Gandalf 1.6 1/10/00 Miloslav Metelka * 6 Gandalf 1.5 1/6/00 Miloslav Metelka * 5 Gandalf 1.4 11/14/99 Miloslav Metelka * 4 Gandalf 1.3 10/23/99 Ian Formanek NO SEMANTIC CHANGE - Sun * Microsystems Copyright in File Comment * 3 Gandalf 1.2 9/10/99 Miloslav Metelka * 2 Gandalf 1.1 7/21/99 Miloslav Metelka * 1 Gandalf 1.0 7/9/99 Miloslav Metelka * $ */